package com.summerbird.mallchat.common.user.service.impl;

import com.summerbird.mallchat.common.common.annotation.RedissonLock;
import com.summerbird.mallchat.common.common.domain.enums.YesOrNoEnum;
import com.summerbird.mallchat.common.common.service.LockService;
import com.summerbird.mallchat.common.user.dao.UserBackpackDao;
import com.summerbird.mallchat.common.user.domain.entity.UserBackpack;
import com.summerbird.mallchat.common.user.domain.enums.IdempotentEnum;
import com.summerbird.mallchat.common.user.service.UserBackpackService;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class UserBackpackServiceImpl implements UserBackpackService {

    @Autowired
    private LockService lockService;

    @Autowired
    private UserBackpackDao userBackpackDao;

    @Autowired
    @Lazy
    private UserBackpackServiceImpl userBackpackService;

    @Override
    public void acquireItem(Long uid, Long itemId, IdempotentEnum idempotentEnum, String businessId) {
        String idempotent = getIdempotent(itemId, idempotentEnum.getType(), businessId);
        userBackpackService.doAcquireItem(uid, itemId, idempotent);
    }

    // 隐藏问题：同类调用
    // 解决办法：
    // 1. 获取当前代理对象。((UserBackpackServiceImpl) AopContext.currentProxy()).doAcquireItem(...);
    // 2. 注入自身对象。   @Autowired
    //                  @Lazy
    //                  private UserBackpackServiceImpl userBackpackService;
    @RedissonLock(key = "#idempotent", waitTime = 5000)//相同幂等如果同时发奖，需要排队等上一个执行完，取出之前数据返回
    public void doAcquireItem(Long uid, Long itemId, String idempotent) {
        UserBackpack userBackpack = userBackpackDao.getByIdempotent(idempotent);
        // 已经获取到物品，直接返回即可，不用报错
        if(Objects.nonNull(userBackpack)){
            return;
        }
        // 发放物品
        UserBackpack newUserBackpack = UserBackpack.builder()
                .itemId(itemId)
                .uid(uid)
                .status(YesOrNoEnum.NO.getStatus())
                .idempotent(idempotent)
                .build();
        userBackpackDao.save(newUserBackpack);
    }

    private String getIdempotent(Long itemId, Integer type, String businessId) {
        return String.format("%d_%d_%s", itemId, type, businessId);
    }
}
